/*
 * Copyright (c) 2024 Black Sesame Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef _DAL_PUBLISHER_H_
#define _DAL_PUBLISHER_H_

#ifdef __cplusplus
extern "C" {
#endif

#include "dal/ret_type.h"
#include "dal/base_type.h"
#include "dal/status.h"
#include "dal/instance_handle.h"
#include "dal/topic.h"
#include "dal/guid.h"
#include "dal/write_params.h"
#include "dal/dds_entity.h"

// User must init callbacks' memory to 0 before using.
typedef struct dal_publisher_listener_callbacks_s
{
    void (*on_offered_deadline_missed)(dal_datawriter_t*,
                                       dal_offered_deadline_missed_status_t*,
                                       void*);
    void (*on_offered_incompatible_qos)(dal_datawriter_t*,
                                        dal_offered_incompatible_qos_status_t*,
                                        void*);
    void (*on_liveliness_lost)(dal_datawriter_t*, dal_liveliness_lost_status_t*, void*);
    void (*on_publication_matched)(dal_datawriter_t*, dal_publication_matched_status_t*, void*);

    // offer callbacks the ability to access external resources, like binding
    // parameters;
    void* data_;
} dal_publisher_listener_callbacks_t;

// User must init callbacks' memory to 0 before using.
typedef struct dal_datawriter_listener_callbacks_s
{
    void (*on_offered_deadline_missed)(dal_datawriter_t*,
                                       dal_offered_deadline_missed_status_t*,
                                       void*);
    void (*on_offered_incompatible_qos)(dal_datawriter_t*,
                                        dal_offered_incompatible_qos_status_t*,
                                        void*);
    void (*on_liveliness_lost)(dal_datawriter_t*, dal_liveliness_lost_status_t*, void*);
    void (*on_publication_matched)(dal_datawriter_t*, dal_publication_matched_status_t*, void*);

    // offer callbacks the ability to access external resources, like binding
    // parameters;
    void* data_;
} dal_datawriter_listener_callbacks_t;

typedef struct dal_datawriter_listener_s
{
    void* handle_;
} dal_datawriter_listener_t;

dal_publisher_listener_t*
dal_create_publisher_listener(dal_publisher_listener_callbacks_t callbacks);
dal_ret_t dal_delete_publisher_listener(dal_publisher_listener_t* listener);

dal_datawriter_listener_t*
dal_create_datawriter_listener(dal_datawriter_listener_callbacks_t callbacks);
dal_ret_t dal_delete_datawriter_listener(dal_datawriter_listener_t* listener);

dal_ret_t dal_publisher_enable(dal_publisher_t* pub);
dal_status_condition* dal_publisher_get_statuscondition(dal_publisher_t* pub);
dal_status_mask_t dal_publisher_get_status_changes(dal_publisher_t* pub);
dal_instance_handle_t dal_publisher_get_instance_handle(dal_publisher_t* pub);

dal_datawriter_t* dal_publisher_create_datawriter(dal_publisher_t* pub,
                                                  dal_topic_t* topic,
                                                  dal_datawriter_qos_t* qos,
                                                  dal_datawriter_listener_t* listener,
                                                  dal_status_mask_t mask);
dal_datawriter_t* dal_publisher_create_datawriter_with_profile(dal_publisher_t* pub,
                                                               dal_topic_t* topic,
                                                               dal_datawriter_qos_t* qos,
                                                               const char* profile_name,
                                                               dal_datawriter_listener_t* listener,
                                                               dal_status_mask_t mask);
dal_ret_t dal_publisher_delete_datawriter(dal_publisher_t* pub, dal_datawriter_t* writer);
dal_datawriter_t* dal_publisher_lookup_datawriter(dal_publisher_t* pub, const char* topic_name);

dal_ret_t dal_publisher_delete_contained_entities(dal_publisher_t* pub);
dal_ret_t dal_publisher_set_qos(dal_publisher_t* pub, dal_publisher_qos_t* qos);
dal_ret_t dal_publisher_get_qos(dal_publisher_t* pub, dal_publisher_qos_t* qos);
dal_ret_t dal_publisher_set_listener(dal_publisher_t* pub,
                                     dal_publisher_listener_t listener,
                                     dal_status_mask_t mask);
dal_publisher_listener_t* dal_publisher_get_listener(dal_publisher_t* pub);
dal_ret_t dal_publisher_suspend_publications(dal_publisher_t* pub);
dal_ret_t dal_publisher_resume_publications(dal_publisher_t* pub);
dal_ret_t dal_publisher_begin_coherent_changes(dal_publisher_t* pub);
dal_ret_t dal_publisher_end_coherent_changes(dal_publisher_t* pub);
dal_ret_t dal_publisher_wait_for_acknowledgments(dal_publisher_t* pub, dal_duration_t max_wait);
dal_domain_participant_t* dal_publisher_get_participant(dal_publisher_t* pub);
dal_ret_t dal_publisher_set_default_datawriter_qos(dal_publisher_t* pub, dal_datawriter_qos_t qos);
dal_ret_t dal_publisher_get_default_datawriter_qos(dal_publisher_t* pub, dal_datawriter_qos_t* qos);
dal_ret_t dal_publisher_copy_from_topic_qos(dal_publisher_t* pub,
                                            dal_datawriter_qos_t* writer_qos,
                                            dal_topic_qos_t a_topic_qos);

dal_ret_t dal_datawriter_enable(dal_datawriter_t* writer);
dal_status_condition dal_datawriter_get_statuscondition(dal_datawriter_t* writer);
dal_status_mask_t dal_datawriter_get_status_changes(dal_datawriter_t* writer);
dal_instance_handle_t dal_datawriter_get_instance_handle(dal_datawriter_t* writer);
dal_instance_handle_t dal_datawriter_register_instance(dal_datawriter_t* writer,
                                                       dal_data instance_data);
dal_instance_handle_t dal_datawriter_register_instance_w_timestamp(dal_datawriter_t* writer,
                                                                   dal_data instance_data,
                                                                   dal_time_t* source_timestamp);
dal_ret_t dal_datawriter_dal_datawriter_unregister_instance(dal_datawriter_t* writer,
                                                            dal_data instance_data,
                                                            dal_instance_handle_t handle);
dal_ret_t dal_datawriter_unregister_instance_w_timestamp(dal_datawriter_t* writer,
                                                         dal_data instance_data,
                                                         dal_instance_handle_t handle,
                                                         dal_time_t* source_timestamp);
dal_ret_t dal_datawriter_write(dal_datawriter_t* writer,
                               dal_data instance_data,
                               dal_instance_handle_t handle);
// only used in fastdds
dal_ret_t dal_datawriter_write_with_params(dal_datawriter_t* writer,
                                           dal_data data,
                                           dal_write_params_t* write_params);
dal_ret_t dal_datawriter_write_w_timestamp(dal_datawriter_t* writer,
                                           dal_data instance_data,
                                           dal_instance_handle_t handle,
                                           dal_time_t* source_timestamp);
dal_ret_t dal_datawriter_dispose(dal_datawriter_t* writer,
                                 dal_data instance_data,
                                 dal_instance_handle_t instance_handle);
dal_ret_t dal_datawriter_dispose_w_timestamp(dal_datawriter_t* writer,
                                             dal_data instance_data,
                                             dal_instance_handle_t instance_handle,
                                             dal_time_t* source_timestamp);
dal_ret_t dal_datawriter_get_key_value(dal_datawriter_t* writer,
                                       dal_data key_holder,
                                       dal_instance_handle_t handle);
dal_instance_handle_t dal_datawriter_lookup_instance(dal_datawriter_t* writer,
                                                     dal_data instance_data);
dal_ret_t dal_datawriter_set_qos(dal_datawriter_t* writer, dal_datawriter_qos_t qos);
dal_ret_t dal_datawriter_get_qos(dal_datawriter_t* writer, dal_datawriter_qos_t* qos);
dal_ret_t dal_datawriter_set_listener(dal_datawriter_t* writer,
                                      dal_datawriter_listener_t* listener,
                                      dal_status_mask_t mask);
dal_datawriter_listener_t* dal_datawriter_get_listener(dal_datawriter_t* writer);
dal_topic_t* dal_datawriter_get_topic(dal_datawriter_t* writer);
dal_publisher_t dal_datawriter_get_publisher(dal_datawriter_t* writer);
dal_ret_t dal_datawriter_wait_for_acknowledgments(dal_datawriter_t* writer,
                                                  dal_duration_t* max_wait);
// Access the status
dal_ret_t dal_datawriter_get_liveliness_lost_status(dal_datawriter_t* writer,
                                                    dal_liveliness_lost_status_t* status);
dal_ret_t
dal_datawriter_get_offered_deadline_missed_status(dal_datawriter_t* writer,
                                                  dal_offered_deadline_missed_status_t* status);
dal_ret_t
dal_datawriter_get_offered_incompatible_qos_status(dal_datawriter_t* writer,
                                                   dal_offered_incompatible_qos_status_t* status);
dal_ret_t dal_datawriter_get_publication_matched_status(dal_datawriter_t* writer,
                                                        dal_publication_matched_status_t* status);
dal_ret_t dal_datawriter_get_matched_subscriptions(dal_datawriter_t* writer,
                                                   InstanceHandleSeq* subscription_handles);
dal_ret_t
dal_datawriter_get_matched_subscription_data(dal_datawriter_t* writer,
                                             SubscriptionBuiltinTopicData* subscription_data,
                                             dal_instance_handle_t subscription_handle);
dal_ret_t dal_datawriter_assert_liveliness(dal_datawriter_t* writer);

dal_guid_t dal_datawriter_get_guid(dal_datawriter_t* writer);

#ifdef __cplusplus
}
#endif

#endif  // _DAL_PUBLISHER_H_
